Skip to content

feat(contracts): add structured event schema with actor+timestamp - #827

Merged
ritik4ever merged 1 commit into
ritik4ever:mainfrom
ezekielcyclops-ux:feat/contract-event-schema
Jul 31, 2026
Merged

feat(contracts): add structured event schema with actor+timestamp#827
ritik4ever merged 1 commit into
ritik4ever:mainfrom
ezekielcyclops-ux:feat/contract-event-schema

Conversation

@ezekielcyclops-ux

@ezekielcyclops-ux ezekielcyclops-ux commented Jul 29, 2026

Copy link
Copy Markdown
Contributor
  • Add actor and timestamp base fields to all 8 event structs (StreamCreated, StreamClaimed, StreamCanceled, StreamPaused, StreamResumed, StreamTransferred, ClawbackExecuted)
  • Add new StreamCompleted event emitted when a stream is fully drained
  • Update all env.events().publish() calls with new fields
  • Add refunded_amount field to StreamCanceled
  • Add claimed_amount field to StreamClaimed
  • Update indexer to parse actor field from all event types
  • Add Completed and Clawback handlers to indexer processEvent()
  • Create docs/CONTRACT_EVENTS.md with full event schema reference

What changed

Testing done

Related issues

Closes #

Checklist

  • I kept the change focused on the related issue.
  • I added or updated tests where useful.
  • I updated documentation where behavior changed.
  • I verified the app still builds or explained why verification was skipped.

closes #596

Summary by CodeRabbit

  • New Features

    • Added a dedicated completion event when a stream is fully claimed.
    • Expanded stream events with consistent actor and timestamp information.
    • Added additional event details, including claimed, refunded, paused, resumed, and transfer data.
  • Bug Fixes

    • Improved event history accuracy by recording the correct actor, recipients, amounts, and timestamps.
  • Documentation

    • Added a complete reference for emitted contract events, field formats, ordering, and event history mappings.

- Add actor and timestamp base fields to all 8 event structs
  (StreamCreated, StreamClaimed, StreamCanceled, StreamPaused,
  StreamResumed, StreamTransferred, ClawbackExecuted)
- Add new StreamCompleted event emitted when a stream is fully drained
- Update all env.events().publish() calls with new fields
- Add refunded_amount field to StreamCanceled
- Add claimed_amount field to StreamClaimed
- Update indexer to parse actor field from all event types
- Add Completed and Clawback handlers to indexer processEvent()
- Create docs/CONTRACT_EVENTS.md with full event schema reference
@vercel

vercel Bot commented Jul 29, 2026

Copy link
Copy Markdown

@ezekielcyclops-ux is attempting to deploy a commit to the ritik4ever's projects Team on Vercel.

A member of the Team first needs to authorize it.

@drips-wave

drips-wave Bot commented Jul 29, 2026

Copy link
Copy Markdown

@ezekielcyclops-ux Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The contract event schemas now share actor and timestamp fields, add event-specific data and StreamCompleted, and update all publishing sites. The indexer maps these fields and payloads into history records, while documentation specifies schemas, ordering, and database mappings.

Changes

Structured contract events

Layer / File(s) Summary
Event schemas and specification
contracts/src/lib.rs, docs/CONTRACT_EVENTS.md
Event structs use shared base fields, StreamClaimed includes cumulative amounts, and StreamCompleted is defined. Documentation specifies schemas, mappings, ordering, and extension steps.
State-change event publishing
contracts/src/lib.rs, docs/CONTRACT_EVENTS.md
Stream creation, claiming, cancellation, transfer, pause, resume, and clawback publish the revised payloads; completed claims additionally emit StreamCompleted.
Indexer event mapping
backend/src/services/indexer.ts
Event history records derive actors from the new contract fields with fallbacks and persist completion, pause, resume, and transfer payload data.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant StellarStreamContract
  participant StellarRPC
  participant Indexer
  participant stream_events
  StellarStreamContract->>StellarRPC: Emit structured event
  StellarRPC->>Indexer: Read event topics and values
  Indexer->>stream_events: Persist mapped event history
Loading

Possibly related PRs

Suggested reviewers: testersweb

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately describes the main change to structured contract events.
Linked Issues check ✅ Passed The PR covers the required event schemas, indexer parsing, one structured event per state change, and documentation for #596.
Out of Scope Changes check ✅ Passed No clear out-of-scope changes are present; the additions align with the event-schema and indexer objectives.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Fix failing CI checks
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/src/services/indexer.ts`:
- Around line 251-254: Update the Claimed event handling near the
recordEventWithDb call to pass value.claimed_amount as the canonical positional
amount instead of value.amount, while preserving value.claimed_amount in the
claimed_amount metadata field and the existing actor/recipient fallback.

In `@docs/CONTRACT_EVENTS.md`:
- Around line 193-204: Update the cancel entry in the Event Ordering Guarantees
section to state that a successful first-time cancel emits exactly one
StreamCanceled event, while canceling an already-canceled stream returns
successfully without publishing another event.
- Around line 16-18: Add the text language identifier to the fenced code block
containing the `(Symbol("Stream"), Symbol("<EventName>"))` example, changing the
opening fence to use ```text while preserving the example content.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b180bd78-1cb2-421b-b371-789b1f5a1633

📥 Commits

Reviewing files that changed from the base of the PR and between b3d32c1 and a3f582c.

📒 Files selected for processing (3)
  • backend/src/services/indexer.ts
  • contracts/src/lib.rs
  • docs/CONTRACT_EVENTS.md

Comment on lines +251 to +254
// actor == recipient for Claimed events
value.actor ?? value.recipient,
value.amount,
{ claimed_amount: value.claimed_amount },

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Persist claimed_amount in the canonical amount column.

Line 253 passes value.amount, while the new claim schema provides value.claimed_amount on Line 254. Because recordEventWithDb stores the positional amount field directly and converts undefined to NULL, claim history will lose its canonical amount even though metadata contains it.

Proposed fix
-          value.amount,
+          value.claimed_amount,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// actor == recipient for Claimed events
value.actor ?? value.recipient,
value.amount,
{ claimed_amount: value.claimed_amount },
// actor == recipient for Claimed events
value.actor ?? value.recipient,
value.claimed_amount,
{ claimed_amount: value.claimed_amount },
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/src/services/indexer.ts` around lines 251 - 254, Update the Claimed
event handling near the recordEventWithDb call to pass value.claimed_amount as
the canonical positional amount instead of value.amount, while preserving
value.claimed_amount in the claimed_amount metadata field and the existing
actor/recipient fallback.

Comment thread docs/CONTRACT_EVENTS.md
Comment on lines +16 to +18
```
(Symbol("Stream"), Symbol("<EventName>"))
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add a language identifier to the fenced block.

This violates MD040 and can fail the documentation lint job.

Proposed fix
-```
+```text
 (Symbol("Stream"), Symbol("<EventName>"))
</details>

<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion

🧰 Tools
🪛 markdownlint-cli2 (0.23.1)

[warning] 16-16: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/CONTRACT_EVENTS.md` around lines 16 - 18, Add the text language
identifier to the fenced code block containing the `(Symbol("Stream"),
Symbol("<EventName>"))` example, changing the opening fence to use ```text while
preserving the example content.

Source: Linters/SAST tools

Comment thread docs/CONTRACT_EVENTS.md
Comment on lines +193 to +204
## Event Ordering Guarantees

Within a single transaction:

- `create_stream` → exactly one `StreamCreated`
- `create_split_stream` → exactly one `StreamCreated` per child stream, in allocation order
- `claim` → exactly one `StreamClaimed`, followed by at most one `StreamCompleted` (only when the stream is fully drained)
- `cancel` → exactly one `StreamCanceled`
- `pause_stream` → exactly one `StreamPaused`
- `resume_stream` → exactly one `StreamResumed`
- `transfer_stream` → exactly one `StreamTransferred`
- `clawback` → exactly one `ClawbackExecuted` (only when `actual_clawback > 0`)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Qualify the cancel ordering guarantee.

Line 200 says every cancel emits an event, but an already-canceled stream returns without publishing one. Document this as a successful first-time cancellation.

Proposed fix
-- `cancel` → exactly one `StreamCanceled`
+- successful first-time `cancel` → exactly one `StreamCanceled`
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
## Event Ordering Guarantees
Within a single transaction:
- `create_stream` → exactly one `StreamCreated`
- `create_split_stream` → exactly one `StreamCreated` per child stream, in allocation order
- `claim` → exactly one `StreamClaimed`, followed by at most one `StreamCompleted` (only when the stream is fully drained)
- `cancel` → exactly one `StreamCanceled`
- `pause_stream` → exactly one `StreamPaused`
- `resume_stream` → exactly one `StreamResumed`
- `transfer_stream` → exactly one `StreamTransferred`
- `clawback` → exactly one `ClawbackExecuted` (only when `actual_clawback > 0`)
## Event Ordering Guarantees
Within a single transaction:
- `create_stream` → exactly one `StreamCreated`
- `create_split_stream` → exactly one `StreamCreated` per child stream, in allocation order
- `claim` → exactly one `StreamClaimed`, followed by at most one `StreamCompleted` (only when the stream is fully drained)
- successful first-time `cancel` → exactly one `StreamCanceled`
- `pause_stream` → exactly one `StreamPaused`
- `resume_stream` → exactly one `StreamResumed`
- `transfer_stream` → exactly one `StreamTransferred`
- `clawback` → exactly one `ClawbackExecuted` (only when `actual_clawback > 0`)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/CONTRACT_EVENTS.md` around lines 193 - 204, Update the cancel entry in
the Event Ordering Guarantees section to state that a successful first-time
cancel emits exactly one StreamCanceled event, while canceling an
already-canceled stream returns successfully without publishing another event.

@ritik4ever
ritik4ever merged commit fd5f1e4 into ritik4ever:main Jul 31, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] Emit structured on-chain events for all contract state changes

2 participants